.TITLE DSDRV .IDENT /12.08/ ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; P. J. BEZEREDI 19-SEP-79 ; ; PREVIOUSLY MODIFIED BY: ; ; P. J. BEZEREDI ; R. T. PERRON ; ; MODIFIED BY: ; ; B. S. MCCARTHY 6-AUG-85 12.08 ; ; BM368 -- ADD CONDITIONAL SKIP OF FIRST DRIVE ; NOT READY ERROR FOR POWERFAIL ; ; RH11/RH70-RS03/RS04 FIXED HEAD DISK DRIVER ; ; MACRO LIBRARY CALLS ; .MCALL HWDDF$,PKTDF$ HWDDF$ ;DEFINE HARDWARE REGISTERS PKTDF$ ;DEFINE I/O PACKET OFFSETS ; ; EQUATED SYMBOLS ; ADR=10 ;ADDRESS BITS SETUP (1=YES) SEL=20 ;PORT SELECT WAIT (1=WAITING) RETRY=8. ;ERROR RETRY COUNT TRE=40000 ;TRANSFER ERROR RSCS1=0 ;CONTROL AND STATUS REGISTER RSWC=2 ;WORD COUNT REGISTER RSBA=4 ;BUS ADDRESS RSDA=6 ;TRACK/SECTOR ADDRESS RSCS2=10 ;SECOND STATUS REGISTER RSDS=12 ;DRIVE STATUS REGISTER RSER=14 ;ERROR REGISTER RSAS=16 ;ATTENTION SUMMARY REGISTER ; ; LOCAL DATA ; ; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLER NUMBER) ; RTTBL: .BLKW R$$JS1 ;RETRY COUNT FOR CURRENT OPERATION PRMSV: .BLKW R$$JS1*5 ;PARAMETER SAVE AREA FOR ERROR RECOVERY ;AND WRITE CHECK FUNCTION ; ; DRIVER DISPATCH TABLE ; DDT$ DS,R$$JS1 ;GENERATE DISPATCH TABLE ;+ ; **-DSINI-RH11/RH70-RS03/RS04 FIXED HEAD DISK CONTROLLER INITIATOR ; ; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O ; REQUEST IS QUEUED AND AT THE END OF A PREVOIUS I/O OPERATION TO PROPA- ; GATE THE EXECUTION OF THE DRIVER. IF THE SPECIFIED UNIT IS NOT BUSY, ; THEN AN ATTEMPT IS MADE TO DEQUEUE THE NEXT I/O REQUEST, ELSE A RETURN ; TO THE CALLER IS EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN ; THE NEXT I/O OPERATION IS INITIATED FOLLOWED BY A RETURN TO THE CALLER. ; ; INPUTS: ; ; R5=ADDRESS OF THE UCB OF THE UNIT TO BE INITIATED. ; ; OUTPUTS: ; ; IF THE SPECIFIED UNIT IS NOT BUSY AND AN I/O REQUEST IS WAITING ; TO BE PROCESSED, THEN THE NEXT REQUEST IS DEQUEUED AND THE I/O ; OPERATION IS INITIATED. ;- .ENABL LSB DSINI: GTPKT$ DS,R$$JS1 ;GET NEXT I/O PACKET TO PROCESS ; ; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT: ; ; R1=ADDRESS OF THE I/O REQUEST PACKET. ; R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB. ; R3=CONTROLLER INDEX. ; R4=ADDRESS OF THE STATUS CONTROL BLOCK. ; R5=ADDRESS OF THE UCB OF THE UNIT TO BE INITIATED. ; ; RH11-RS03/RS04 FIXED HEAD DISK I/O REQUEST PACKET FORMAT: ; ; WD. 00 -- I/O QUEUE THREAD WORD. ; WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER. ; WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK. ; WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTOR TASK HEADER. ; WD. 04 -- FIRST LUN WORD IN REQUESTORS TASK HEADER. ; WD. 05 -- I/O FUNCTION CODE. ; WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK. ; WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK. ; WD. 10 -- I/O STATUS BLOCK ADDRESS (DISPLACEMENT + 140000). ; WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE. ; WD. 12 -- MEMORY EXTENSION BITS (BITS 4 AND 5) OF I/O TRANSFER. ; WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER. ; WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED. ; WD. 15 -- NOT USED. ; WD. 16 -- BITS <0:7> = HIGH LBN, BITS <8:15> NOT USED. ; WD. 17 -- LOW LBN OF I/O REQUEST. ; WD. 20 -- RELOCATION BIAS OF REGISTER BLOCK ELSE NOT USED. ; WD. 21 -- REGISTER BLOCK ADDRESS (DISPLACEMENT + 140000). ; BICB #ADR!SEL,U.CW2+1(R5) ;CLEAR FLAGS MOV #RETRY,RTTBL(R3);SET RETRY COUNT CALL $VOLVD ;VALIDATE VOLUME VALID BCS 10$ ;IF CS WE FAILED TST R0 ;TRANSFER FUNCTION? BMI DSUBMP ;IF MI YES TST I.PRM+2(R1) ;SIZE THE DISK? BPL 10$ ;IF PL NO CALL $RQCND ;REQUEST CONTROLLER FOR DATA TRANSFER MOV @S.KRB(R4),R2 ;RETREIVE CSR ADDRESS MOVB U.UNIT(R5),RSCS2(R2) ;SELECT THE UNIT MOV S.PKT(R4),R1 ;RETREIVE I/O PACKET ADDRESS MOVB #111,(R2) ;CLEAR THE DRIVE BIT #10000,RSCS2(R2);DOES THE DRIVE EXIST? BEQ 5$ ;IF EQ YES MOVB #TRE/256.,RSCS1+1(R2) ;CLEAR THE CONTROLLER MOV #IE.SZE&377,R0 ;UNABLE TO SIZE DEVICE BICB #US.VV,U.STS(R5);RESET VOLUME VALID CALL $RLCN ;RELEASE THE CONTROLLER BR 10$ ;EXIT 5$: CALL $CRPAS ;PASS CONTROLLER REGISTERS TO TASK MOV #IS.SUC&377,R0 ;SET SUCCESSFUL OPERATION BR 50$ ; 10$: CALL $IODON ;FINISH I/O BR DSINI ;GET NEXT PACKET TO PROCESS ; ; NOW REQUEST THE CONTROLLER AND DETERMINE IF THE UNIBUS ADDRESS IS ; ALREADY IN THE FORMAT FOR THE MASSBUS CONTROLLER OR THE UNIBUS MAP ; FOR 22-BIT PROCESSORS WITHOUT RH CONTROLLERS. ; DSUBMP: BITB #ADR,U.CW2+1(R5);ADDRESS BITS ALREADY SETUP? BNE DSINIO ;IF NE YES BISB #ADR,U.CW2+1(R5);SHOW ADDRESS BITS SETUP CALL $RQCND ;REQUEST CONTROLLER FOR DATA TRANSFER MOV S.KRB(R4),R1 ;RETREIVE KRB ADDRESS BIT #FE.EXT,$FMASK ;22-BIT ADDRESSING ENABLED? BEQ 20$ ;IF EQ NO BIT #KS.MBC,K.STS(R1) ;YES, IS THIS A 22-BIT CONTROLLER? BNE 30$ ;IF NE YES CALL $STMAP ;SETUP UNIBUS MAP ADDRESS 20$: ASL U.BUF(R5) ;SHIFT BITS <4:5> TO BITS <8:9> ASL U.BUF(R5) ;... ASL U.BUF(R5) ;... ASL U.BUF(R5) ;... BIT #FE.EXT,$FMASK ;22-BIT ADDRESSING ENABLED? BEQ 30$ ;IF EQ NO CALL $MPUBM ;MAP UNIBUS TO TRANSFER ; ; CONVERT THE I/O FUNCTION CODE TO IT'S HARDWARE EQUIVALENT. ; 30$: MOV S.PKT(R4),R1 ;RETREIVE I/O PACKET ADDRESS CMP #IO.WCK!IQ.UMD,I.FCN(R1) ;DIAGNOSTIC WRITE CHECK? BNE 40$ ;IF NE NO BISB #151,U.BUF(R5) ;YES, SET FUNCTION CODE BR 60$ ; 40$: MOV #IE.IFC&377,R0 ;ASSUME ILLEGAL FUNCTION BISB #171,U.BUF(R5) ;ASSUME READ LOGICAL FUNCTION CMPB #IO.RLB/256.,I.FCN+1(R1) ;READ LOGICAL FUNCTION? BHIS 55$ ;IF HIS FUNCTION IS LEGAL 50$: MOV @S.KRB(R4),R2 ;RETREIVE CSR ADDRESS MOVB U.UNIT(R5),RSCS2(R2) ;SELECT DRIVE CALLR DSFIN1 ;FINISH UP 55$: BEQ 60$ ;IF EQ FUNCTION IS READ SUB #10,U.BUF(R5) ;CONVERT TO WRITE LOGICAL FUNCTION ; ; VALIDATE AND CONVERT LBN. ; 60$: CALL $BLKCK ;CHECK LOGICAL BLOCK NUMBER CMP #2,U.PRM+2(R5) ;RS04 DRIVE? BEQ 70$ ;IF EQ YES ASL R0 ;MULTIPLY RS03 BLOCK 70$: ASL R0 ;CONVERT TO SECTOR AND TRACK ADDRESS MOV R0,I.PRM+12(R3) ;SAVE DISK ADDRESS MOV S.KRB(R4),R1 ;RETRIEVE KRB ADDRESS MOVB K.CON(R1),R1 ;RETRIEVE CONTROLLER INDEX MUL #5,R1 ;SETUP AN INDEX INTO ... ADD #PRMSV,R1 ;... PARAMETER SAVE AREA MOV U.BUF(R5),(R1)+ ;SAVE PARAMETERS MOV U.BUF+2(R5),(R1)+ ;... MOV U.CNT(R5),(R1)+ ;... MOV I.PRM+10(R3),(R1)+ ;... MOV I.PRM+12(R3),(R1)+ ;... .DSABL LSB ; ; **-DSINIO-INTIATE AN I/O OPERATION ; ; THIS ROUTINE WILL INITIATE THE DATA TRANSFER OPERATION. AT THIS ; POINT THE CONTROLLER MUST BE REQUESTED FOR A DATA TRANSFER. ; ; INPUTS: ; ; R4=ADDRESS OF THE SCB. ; R5=ADDRESS OF THE UCB. ; DSINIO: MOV @S.KRB(R4),R2 ;GET CSR ADDRESS MOV S.PKT(R4),R1 ;GET I/O PACKET ADDRESS MOVB U.UNIT(R5),RSCS2(R2) ;SELECT UNIT ; ; DETERMINE IF DRIVE'S PORT IS SEIZED BY THIS CONTROLLER. ; CLR RSDS(R2) ;ATTEMPT TO SEIZE THE DRIVE BIT #400,RSDS(R2) ;DID THE DRIVE SEIZE? BNE 5$ ;IF NE YES MOVB #100,(R2) ;RE-ENABLE INTERRUPTS BISB #SEL,U.CW2+1(R5);SET PORT SELECT WAIT FLAG MOVB S.ITM(R4),S.CTM(R4) ;SET CURRENT DEVICE TIMEOUT COUNT CALLR $RLCN ;RELEASE CONTROLLER AND EXIT ; ; LOAD CONTROLLER REGISTERS FOR DATA TRANSFER. ; 5$: MOV #TRE!11,(R2) ;CLEAR CONTROLLER AND DRIVE ERRORS ADD #RSCS2,R2 ;POINT TO SECOND CSR MOV I.PRM+12(R1),-(R2) ;INSERT DISK ADDRESS MOV U.BUF+2(R5),-(R2) ;INSERT BUFFER ADDRESS MOV U.CNT(R5),-(R2) ;INSERT NUMBER OF BYTES TO TRANSFER ROR (R2) ;CONVERT TO WORD COUNT NEG (R2) ;MAKE NEGATIVE WORD COUNT TST -(R2) ;POINT TO CSR REGISTER ; ; TEST FOR DRIVE NOT READY CONDITIONS. ; MOV #IE.DNR&377,R0 ;ASSUME DRIVE NOT READY MOV RSDS(R2),R3 ;GET CONTENTS OF DRIVE STATUS REGISTER COM R3 ;COMPLEMENT STATUS BIT #10200,R3 ;DRIVE READY AND ON-LINE? BEQ 20$ ;IF EQ YES BITB #US.SPU,U.STS(R5) ;IS DRIVE SPINNING UP? BEQ 10$ ;IF EQ NO BITB #US.VV,U.STS(R5);WAS THE VOLUME PREVIOUSLY MOUNTED? BEQ DSPWF1 ;IF EQ NO BR DSPWF0 ;YES, WAIT FOR IT TO SPIN UP 10$: BITB #IQ.UMD,I.FCN(R1) ;DIAGNOSTIC OPERATION BEQ 15$ ;IF EQ NO CALLR DSDIAG ;LOG DIAGNOSTIC DRIVE NOT READY 15$: ;REFERENCE LABEL .IF DF S2.NRD BIT #S2.NRD,S.ST2(R4) ;IS THIS FIRST DRIVE NOT READY? BNE 16$ ;IF NE NO, GO LOG ERROR BIS #S2.NRD,S.ST2(R4) ;INDICATE FIRST DRIVE NOT READY JMP DSPWF1 ;GO DO A RETRY 16$: BIC #S2.NRD,S.ST2(R4) ;CLEAR FIRST DRIVE NOT READY .ENDC ; DF S2.NRD CALL $DVERR ;LOG DRIVE NOT READY ERROR CALLR DSFIN ;FINISH UP 20$: BICB #US.SPU,U.STS(R5) ;RESET DRIVE SPINNING UP BICB #S3.SPU,S.ST3(R4) ;CLEAR PORT SPINNING UP FLAGS MOV S.KRB(R4),R3 ;GET CURRENT KRB ADDRESS MOV R3,R1 ;COPY KRB ADDRESS ; ; START THE DATA TRANSFER OPERATION. ; MTPS #PR5 ;;;DISABLE INTERRUPTS BIT #FE.EXT,$FMASK ;;;22-BIT ADDRESSING ENABLED? BEQ 30$ ;;;IF EQ NO BIT #KS.MBC,K.STS(R3) ;;;IS THIS A 22-BIT CONTROLLER? BEQ 30$ ;;;IF EQ NO ADD K.OFF(R3),R1 ;;;POINT TO UCB TABLE MOV KE.RHB(R1),R1 ;;;RETREIVE RHBAE OFFSET ADD R2,R1 ;;;FORM AN I/O PAGE ADDRESS MOVB U.BUF+1(R5),(R1);;;SET MEMORY EXTENSION BITS MOVB U.BUF(R5),(R2) ;;;START FUNCTION BR 40$ ;;; 30$: MOV U.BUF(R5),(R2) ;;;START FUNCTION 40$: CLR S.FRK+2(R4) ;;;INIT FORK INTERLOCK MOVB S.ITM(R4),S.CTM(R4) ;;;SET TIMEOUT COUNT BIS #KS.DIP,K.STS(R3) ;;;SET DATA TRANSFER IN PROGRESS BIS #S2.ACT,S.ST2(R4) ;;;SHOW I/O IS ACTIVE MTPS #0 ;ALLOW INTERRUPTS ; ; CANCEL I/O OPERATION IS A NOP FOR FILE STRUCTURED DEVICES. ; DSCAN: RETURN ;NOP FOR RS03/RS04 ;+ ; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND ; CAUSES NO IMMEDIATE ACTION ON THE UNIT. THE CURRENT TIMEOUT ; COUNT IS EXTENDED SO THAT IF THE UNIT WAS BUSY IT WILL HAVE ; SUFFICIENT TIME TO SPIN BACK UP. THE NEXT I/O REQUEST TO ANY ; UNIT WILL BE SUSPENDED FOR AT LEAST THE EXTENDED TIMEOUT UNLESS ; THE UNIT IS ALREADY READY. ;- DSPWF: TSTB S.STS(R4) ;IS THIS UNIT CURRENTLY BUSY? BEQ DSPWF2 ;IF EQ NO DSPWF0: MOVB #8.,S.STS(R4) ;WAIT A MAXIMUM OF 32 SECONDS DSPWF1: MOVB S.ITM(R4),S.CTM(R4) ;4 SECONDS AT A TIME DSPWF2: BISB #US.SPU,U.STS(R5) ;SET UNIT SPINNING UP DSPWF3: CALLR $RLCN ;RELEASE CONTROLLER (IF NECESSARY) ;+ ; **-$DSINT-RH11-RS03/RS04 FIXED HEAD DISK CONTROLLER ; INTERRUPT SERVICE ROUTINE ;- $DSINT::BR DSFRK ;;;ENTRY POINT FOR DATA TRANSFERS TST S.FRK+2(R4) ;;;ARE INTERRUPTS ALLOWED? BNE DSCAN ;;;IF NE NO CALL $FORK ;;;CREATE A SYSTEM PROCESS DSFRK: CALL $RQCND ;REQUEST CONTROLLER FOR DATA TRANSFER BITB #SEL,U.CW2+1(R5);WAITING FOR PORT TO SELECT? BEQ 5$ ;IF EQ NO BICB #SEL,U.CW2+1(R5);CLEAR PORT SELECT WAIT FLAG JMP DSINIO ;YES, GO DO THE TRANSFER 5$: MOV S.KRB(R4),R3 ;GET CURRENT KRB ADDRESS MOVB K.CON(R3),R3 ;RETREIVE CONTROLLER INDEX MOV U.SCB(R5),R4 ;GET ADDRESS OF SCB MOV #IS.SUC&377,R0 ;ASSUME SUCCESSFUL TRANSFER MOV @S.KRB(R4),R2 ;GET CSR ADDRESS MOVB U.UNIT(R5),RSCS2(R2) ;SELECT UNIT TSTB S.STS(R4) ;IS THIS UNIT BUSY? BNE 15$ ;IF NE YES CLR S.FRK+2(R4) ;RESET FORK INTERLOCK MOV #TRE!11,(R2) ;CLEAR CONTROLLER AND DRIVE BIT #S2.MAD,S.ST2(R4) ;MULTI-ACCESS DEVICE? BNE 10$ ;IF NE YES MOVB #100,(R2) ;NO, JUST RE-ENABLE INTERRUPTS BR DSPWF3 ;RELEASE CONTROLLER AND EXIT 10$: MOVB #113,(R2) ;RELEASE THE DRIVE BISB #S3.DRL,S.ST3(R4) ;SHOW DUAL ACCESS UNIT RELEASED BR DSPWF3 ;RELEASE CONTROLLER AND EXIT ; ; THE UNIT WAS BUSY. NOW CHECK FOR ERRORS. ; 15$: BITB #US.SPU,U.STS(R5) ;ARE WE SPINNING UP? BNE DSREST ;IF NE YES MOV S.PKT(R4),R1 ;GET I/O PACKET ADDRESS BITB #IQ.UMD,I.FCN(R1) ;DIAGNOSTIC FUNCTION EXECUTED? BNE DSDIAG ;IF NE YES BIT #60000,(R2) ;ANY ERRORS? BEQ DSWCHK ;IF EQ NO MOV RSWC(R2),R0 ;GET NEGATIVE WORDS REMAINING ASL R0 ;CONVERT TO NEGATIVE BYTES ADD U.CNT(R5),R0 ;CALCULATE BYTES ACTUALLY TRANSFERED SUB #512.,R0 ;SUBTRACT OUT BLOCK IN ERROR BLE 20$ ;IF LE NO GOOD BYTES TRANSFERED BIT #S2.EIP,S.ST2(R4) ;ERROR ALREADY IN PROGRESS BEQ 20$ ;IF EQ NO ; ; WE GOT AN ERROR BUT SOME GOOD DATA WAS TRANSFERED. THIS ; INDICATES THAT WE RECOVERED FROM THE PREVIOUS ERROR. ; CALL DSCALC ;CALCULATE NEW DISK PARAMETERS MOV R2,-(SP) ;SAVE CSR ADDRESS MOVB RTTBL(R3),R2 ;GET FINAL ERROR RETRY COUNT BIS #RETRY*256.,R2 ;MERGE STARTING RETRY COUNT MOV #IS.SUC&377,R0 ;THIS RECOVERY WAS SUCCESSFUL CALL $FNERL ;FINISH ERROR LOGGING PROCESS MOV #RETRY,RTTBL(R3);SET INITIAL RETRY COUNT MOV (SP)+,R2 ;RESTORE CSR ADDRESS 20$: CALL $DVERR ;LOG DEVICE ERROR MOV #IE.WCK&377,R0 ;ASSUME WRITE CHECK ERROR BIT #4000,RSCS2(R2) ;WRITE CHECK ERROR? BNE DSRTRY ;IF NE YES MOV #IE.VER&377,R0 ;ASSUME UNRECOVERABLE ERROR MOV RSER(R2),R1 ;GET CONTENTS OF ERROR REGISTER BIT #47007,R1 ;HARD ERROR? BNE 30$ ;IF NE YES BIT #14000,RSCS2(R2);NEM OR NED? BNE 30$ ;IF NE YES TST RSCS2(R2) ;DATA LATE ERROR? BPL DSRTRY ;IF PL NO CALL DSCALC ;YES, CALCULATE NEW PARAMETERS BR DSRTRY ;RETRY FROM BLOCK IN ERROR 30$: BIT #4000,R1 ;WRITE LOCK ERROR? BEQ DSFIN ;IF EQ NO MOV #IE.WLK&377,R0 ;SET WRITE LOCK ERROR BR DSFIN ;FINISH I/O ; ; DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING REPEATED ; UNLESS THE REQUEST WAS DIAGNOSTIC. TIMEOUTS ARE USUALLY CAUSED ; BY POWERFAILURE BUT MAY ALSO BE THE RESULT OF A HARDWARE FAILURE. ; DSOUT: BITB #US.SPU,U.STS(R5) ;;;IS DRIVE SPINNING UP? BEQ 10$ ;;;IF EQ NO DECB S.STS(R4) ;;;HAVE WE WAITED ENOUGH YET? BEQ 10$ ;;;IF EQ YES MTPS #0 ;;;ALLOW INTERRUPTS CALL $RQCND ;REQUEST CONTROLLER FOR TRANSFER BR DSREST ;RETRY ENTIRE OPERATION 10$: INCB S.STS(R4) ;;;LEAVE CONTROLLER BUSY BICB #US.SPU,U.STS(R5) ;;;RESET DRIVE SPINNING UP MTPS #0 ;;;ALLOW INTERRUPTS CALL $RQCND ;REQUEST CONTROLLER FOR TRANSFER MOV S.KRB(R4),R2 ;GET CURRENT KRB ADDRESS MOVB K.CON(R2),R3 ;RETREIVE CONTROLLER INDEX MOV (R2),R2 ;RETREIVE CSR ADDRESS MOVB U.UNIT(R5),RSCS2(R2) ;SELECT UNIT CALL $DVTMO ;LOG DEVICE TIMEOUT BITB #SEL,U.CW2+1(R5);WAITING FOR PORT TO SELECT? BNE DSFIN1 ;IF NE YES, WE DIDN'T GET IT BCC DSRTRY ;IF CC TIMEOUT DURING NORMAL FUNCTION DSDIAG: CALL $CRPAS ;PASS CONTROLLER REGISTERS TO TASK BR DSFIN ;DIAGNOSTIC PROCESSING COMPLETE ; ; RETRY THE CURRENT OPERATION. ; DSRTRY: MOV S.PKT(R4),R1 ;GET I/O PACKET ADDRESS BITB #IQ.X,I.FCN(R1) ;INHIBIT RETRIES? BNE DSFIN ;IF NE YES DEC RTTBL(R3) ;RETRY FUNCTION? BLE DSFIN ;IF LE NO DSREST: MOVB #111,(R2) ;CLEAR THE DRIVE CALLR DSUBMP ;RESTART OPERATION ; ; TEST FOR WRITE CHECK OPERATION. ; DSWCHK: BITB #IO.WLC&377,I.FCN(R1) ;WRITE FOLLOWED BY WRITE CHECK? BNE 10$ ;IF NE YES BITB #US.WCK,U.STS(R5) ;WRITE CHECK ENABLED BY MCR? BEQ DSFIN ;IF EQ NO 10$: MOVB U.BUF(R5),R1 ;GET LAST FUNCTION CMPB #171,R1 ;WAS IT A READ? BEQ DSFIN ;IF EQ YES CMPB #161,R1 ;WAS LAST FUNCTION A WRITE? BNE DSFIN ;IF NE NO MOV #RETRY,RTTBL(R3);REINITIALIZE RETRY COUNT MOV S.PKT(R4),R1 ;RESTORE I/O PACKET ADDRESS MUL #5,R3 ;FORM AN INDEX INTO ... ADD #PRMSV,R3 ;... PARAMETER SAVE AREA MOV (R3)+,U.BUF(R5) ;RESTORE PARAMETERS MOV (R3)+,U.BUF+2(R5) ;... MOV (R3)+,U.CNT(R5) ;... MOV (R3)+,I.PRM+10(R1) ;... MOV (R3)+,I.PRM+12(R1) ;... MOVB #151,U.BUF(R5) ;SET WRITE CHECK FUNCTION BR DSREST ;START WRTIE CHECK OPERATION ; ; **-DSFIN-FINISH I/O OPERATION ; ; THIS ROUTINE WILL SET THE ACTUAL BYTES TRANSFERED PARAMETER, THE ; ERROR LOGGING RETRY COUNTS AND CALL $IODON. A CHECK WILL BE MADE ; FOR ANY PENDING ATTENTIONS AND THE CONTROLLER WILL BE RELEASED. ; ; INPUTS: ; ; R0=SUCCESS/ERROR CODE ; R2=ADDRESS OF CONTROLLER CSR ; R4=ADDRESS OF THE SCB ; R5=ADDRESS OF THE UCB ; DSFIN: MOV RSWC(R2),R1 ;GET WORDS REMAINING TO TRANSFER ASL R1 ;CONVERT TO BYTES LEFT TO TRANSFER ADD U.CNT(R5),R1 ;CALCULATE BYTES ACTUALLY TRANSFERED DSFIN1: MOVB #11,(R2) ;CLEAR THE DRIVE MOV #TRE,(R2) ;NOW CLEAR THE DRIVE MOV S.KRB(R4),R3 ;GET CURRENT KRB ADDRESS BICB #SEL,U.CW2+1(R5);CLEAR PORT SELECT WAIT FLAG 10$: TSTB RSAS(R2) ;ANY ATTENTIONS PENDING? BEQ 20$ ;IF EQ NO BISB #100,(R2) ;RE-DISPATCH TO INTERRUPT HANDLER BR 10$ ;TRY AGAIN 20$: BIT #S2.MAD,S.ST2(R4) ;DUAL ACCESS DEVICE? BEQ 30$ ;IF EQ NO BITB #S3.NRL,S.ST3(R4) ;SHOULD WE RELEASE THE DRIVE? BEQ 35$ ;IF EQ YES 30$: MOVB #100,(R2) ;RE-ENABLE INTERRUPTS BR 40$ ; 35$: BISB #S3.DRL,S.ST3(R4) ;SHOW DUAL ACCESS UNIT RELEASED MOVB #113,(R2) ;RE-ENABLE INTERRUPTS AND RELEASE DRIVE 40$: MOVB K.CON(R3),R3 ;RETREIVE CONTROLLER INDEX MOVB RTTBL(R3),R2 ;GET FINAL ERROR RETRY COUNT BIS #RETRY*256.,R2 ;MERGE STARTING RETRY COUNT CALL $RLCN ;RELEASE CONTROLLER CLR S.FRK+2(R4) ;ALLOW INTERRUPTS CALL $IODON ;FINISH I/O OPERATION JMP DSINI ;PROCESS NEXT REQUEST ; ; THE TRANSFER STOPPED DUE TO A RETRYABLE ERROR CONDITION. WE ; WILL NOW BACKUP THE WORD COUNT, BUS ADDRESS AND TRACK/SECTOR ; ADDRESS BY ONE BLOCK AND RETRY THE TRANSFER FROM THIS POINT. ; THIS IS DONE TO PREVENT THE ERROR CONDITION FROM RECURRING DUE ; TO A LONG TRANSFER. ; DSCALC: MOV RSWC(R2),R0 ;GET NEGATIVE WORDS REMAINING BNE 10$ ;IF NE WE HAD A PARTIAL TRANSFER MOV #-1,R0 ;DLT ON LAST WORD, FAKE PARTIAL XFR 10$: ASL R0 ;CONVERT TO NEGATIVE BYTES ADD U.CNT(R5),R0 ;CALCULATE BYTES ACTUALLY TRANSFERED BIC #777,R0 ;GET BLOCKS ACTUALLY TRANSFERED SUB R0,U.CNT(R5) ;REDUCE BYTES REMAINING TO TRANSFER BEQ 30$ ;IF EQ NO MORE BYTES TO TRANSFER ADD R0,U.BUF+2(R5) ;UPDATE STARTING BUFFER ADDRESS ADCB U.BUF+1(R5) ;AND THE MEMORY EXTENSION BITS BIT #FE.EXT,$FMASK ;IS 22-BIT ADDRESSING ENABLED? BEQ 15$ ;IF EQ NO MOV S.KRB(R4),R1 ;RETRIEVE THE KRB ADDRESS BIT #KS.MBC,K.STS(R1) ;IS THIS A 22-BIT MASSBUS DEVICE? BNE 15$ ;IF NE YES ADD K.OFF(R1),R1 ;POINT TO UMR AREA+2 ADD R0,-(R1) ;CALCULATE NEW REAL ADDRESS ADCB -(R1) ;... 15$: MOV S.PKT(R4),R1 ;RETRIEVE I/O PACKET ADDRESS SWAB R0 ;GET BLOCKS*2 TRANSFERED CMP #2,U.PRM+2(R5) ;RS04 DRIVE? BEQ 20$ ;IF EQ YES ASL R0 ;GET BLOCKS*4 20$: ADD R0,I.PRM+12(R1) ;UPDATE DISK ADDRESS RETURN ; 30$: ADD R0,U.CNT(R5) ;YES, BACKUP BYTES TO TRANSFER RETURN ; .END